﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ComboBoxExample
{
    [TemplateVisualState(Name = WP7ComboBoxItem.StateUnselected, GroupName = WP7ComboBoxItem.GroupSelection)]
    [TemplateVisualState(Name = WP7ComboBoxItem.StateSelected, GroupName = WP7ComboBoxItem.GroupSelection)]
    [TemplateVisualState(Name = WP7ComboBoxItem.StateSelectedUnfocused, GroupName = WP7ComboBoxItem.GroupSelection)]
    [TemplateVisualState(Name = WP7ComboBoxItem.StateUnfocused, GroupName = WP7ComboBoxItem.GroupFocus)]
    [TemplateVisualState(Name = WP7ComboBoxItem.StateFocused, GroupName = WP7ComboBoxItem.GroupFocus)]
    [TemplateVisualState(Name = WP7ComboBoxItem.StateNormal, GroupName = WP7ComboBoxItem.GroupCommon)]
    [TemplateVisualState(Name = WP7ComboBoxItem.StateMouseOver, GroupName = WP7ComboBoxItem.GroupCommon)]
    public class WP7ComboBoxItem : ContentControl
    {
        private const string GroupSelection = "SelectionStates";
        private const string StateSelected = "Selected";
        private const string StateUnselected = "Unselected";
        private const string StateSelectedUnfocused = "SelectedUnfocused";
        private const string GroupCommon = "CommonStates";
        private const string StateNormal = "Normal";
        private const string StateMouseOver = "MouseOver";

        internal const string GroupFocus = "FocusStates";
        internal const string StateFocused = "Focused";
        internal const string StateUnfocused = "Unfocused";

        public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(WP7ComboBoxItem), new PropertyMetadata(OnIsSelectedChanged));

        internal bool IsFocused { get; private set; }
        internal bool IsMouseOver { get; private set; }
        internal object Item { get; set; }
        internal WP7ComboBox ParentComboBox { get; set; }

        public WP7ComboBoxItem()
        {
            TabNavigation = KeyboardNavigationMode.Local;
            IsTabStop = true;
            MouseLeftButtonDown += ((sender, e) => this.OnMouseLeftButtonDown(e));
            GotFocus += ((sender, e) => this.OnGotFocus(e));
            LostFocus += ((sender, e) => this.OnLostFocus(e));
            Loaded += delegate { this.ChangeVisualState(false); };
            DefaultStyleKey = typeof(WP7ComboBoxItem);
        }

        public bool IsSelected
        {
            get { return (bool)this.GetValue(IsSelectedProperty); }
            set
            {
                SetValue(IsSelectedProperty, value);
            }
        }

        private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((WP7ComboBoxItem)d).ChangeVisualState();
        }

        internal void ChangeVisualState()
        {
            this.ChangeVisualState(true);
        }

        internal void ChangeVisualState(bool useTransitions)
        {
            if (this.ParentComboBox != null)
            {
                if (this.IsMouseOver)
                {
                    GoToState(useTransitions, new[] { StateMouseOver, StateNormal });
                }
                else
                {
                    GoToState(useTransitions, new[] { StateNormal });
                }
                if (this.IsSelected)
                {
                    if (ComboBox.GetIsSelectionActive(this.ParentComboBox))
                    {
                        GoToState(useTransitions, new[] { StateSelected, StateUnselected });
                    }
                    else
                    {
                        GoToState(useTransitions, new[] { StateSelectedUnfocused, StateSelected, StateUnselected });
                    }
                }
                else
                {
                    GoToState(useTransitions, new[] { StateUnselected });
                }
                if (this.IsFocused)
                {
                    GoToState(useTransitions, new[] { StateFocused, StateUnfocused });
                }
                else
                {
                    GoToState(useTransitions, new[] { StateUnfocused });
                }
            }
        }

        internal void GoToState(bool useTransitions, params string[] stateNames)
        {
            if (stateNames != null)
            {
                foreach (string stateName in stateNames)
                {
                    if (VisualStateManager.GoToState(this, stateName, useTransitions))
                    {
                        return;
                    }
                }
            }
        }

        internal new void OnGotFocus(RoutedEventArgs e)
        {
            this.IsFocused = true;
            this.ChangeVisualState();
            if (this.ParentComboBox != null)
            {
                this.ParentComboBox.NotifyComboBoxItemGotFocus(this);
            }
        }

        internal new void OnLostFocus(RoutedEventArgs e)
        {
            this.IsFocused = false;
            this.ChangeVisualState();
            if (this.ParentComboBox != null)
            {
                this.ParentComboBox.NotifyListItemLostFocus(this);
            }
        }

        internal new void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            if (!e.Handled)
            {
                e.Handled = true;
                if (Focus() && (this.ParentComboBox != null))
                {
                    this.ParentComboBox.NotifyListItemClicked(this);
                }
            }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this.ChangeVisualState(false);
        }
    }
}
